#include "stdafx.h"
#include "SceneManager.h"
#include "ResourceManager.h"
#include "Object.h"
#include "Camera.h"
#include "VideoDriver.h"
#include "Utils.h"

cSceneManager*	cSceneManager::ms_Instance = NULL;

cSceneManager::~cSceneManager()
{
	for (unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		SAFE_DEL(m_vObjects[i]);
	}
	m_vObjects.clear();
}

cSceneManager* cSceneManager::GetInstance()
{
	if (ms_Instance == NULL)
	{
		ms_Instance = new cSceneManager();
	}
	return ms_Instance;
}

void cSceneManager::DestroyInstance()
{
	SAFE_DEL(ms_Instance);
}

void cSceneManager::LoadScene(const char *file_url)
{
	FILE		*pFile;
	char		buffer[MAX_LENGTH];
	char		scan_buffer[MAX_LENGTH];
	int			iStart;
	bool		hasReadData = false;
	cObject		*pObject;

	memset(buffer, '\0', MAX_LENGTH);
	memset(scan_buffer, '\0', MAX_LENGTH);

	fopen_s(&pFile, file_url, "r");

	while (!feof(pFile))
	{
		if (!hasReadData)
		{
			ReadLine(pFile, buffer);
			ScanString(buffer, scan_buffer);
		}
		else
		{
			hasReadData = false;
		}

		if (_strcmpi(scan_buffer, "#Camera") == 0)
		{
			hasReadData = true;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "POSITION") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vPos.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vPos.y, iStart);
					ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vPos.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "LOOKAT") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vLookAt.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vLookAt.y, iStart);
					ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vLookAt.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "UP") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vUp.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vUp.y, iStart);
					ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_vUp.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "SPEED") == 0)
				{
					ScanNumberFloat32(buffer, &cCamera::GetInstance()->m_fSpeed, iStart);
				}
			}
		}

		if (_strcmpi(scan_buffer, "#Light") == 0)
		{
			hasReadData = true;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "TYPE") == 0)
				{
					ScanNumberInt32(buffer, &cSceneManager::GetInstance()->m_light.type, iStart);
				}
				else if (_strcmpi(scan_buffer, "POSITION") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.position.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.position.y, iStart);
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.position.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "AMBIENT") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.ambient.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.ambient.y, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.ambient.z, iStart);
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.ambient.w, iStart);
				}
				else if (_strcmpi(scan_buffer, "DIFFUSE") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.diffuse.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.diffuse.y, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.diffuse.z, iStart);
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.diffuse.w, iStart);
				}
				else if (_strcmpi(scan_buffer, "SPECULAR") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.specular.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.specular.y, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.specular.z, iStart);
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.specular.w, iStart);
				}
				else if (_strcmpi(scan_buffer, "CONSTANT_ATTENUATION") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.constantAttenuation, iStart);
				}
				else if (_strcmpi(scan_buffer, "LINEAR_ATTENUATION") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.linearAttenuation, iStart);
				}
				else if (_strcmpi(scan_buffer, "QUADRATIC_ATTENUATION") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.quadraticAttenuation, iStart);
				}
				else if (_strcmpi(scan_buffer, "SHININESS") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.shininess, iStart);
				}
				else if (_strcmpi(scan_buffer, "WEIGHT") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_light.weight, iStart);
				}
			}
		}

		if (_strcmpi(scan_buffer, "#Terrain") == 0)
		{
			hasReadData = true;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "MAX_HEIGHT") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.maxHeight, iStart);
				}
				else if (_strcmpi(scan_buffer, "FOG_START") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogStart, iStart);
				}
				else if (_strcmpi(scan_buffer, "FOG_LENGTH") == 0)
				{
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogLength, iStart);
				}
				else if (_strcmpi(scan_buffer, "FOG_COLOR") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogColor.x, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogColor.y, iStart);
					iStart = ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogColor.z, iStart);
					ScanNumberFloat32(buffer, &cSceneManager::GetInstance()->m_terrain.fogColor.w, iStart);
				}
			}
		}

		if (_strcmpi(scan_buffer, "#VideoDriver") == 0)
		{
			hasReadData = true;
			int id;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "FBO_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBOShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "FBO_BLACK_AND_WHITE_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBOBlackAndWhiteShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "FBO_BLUR_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBOBlurShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "FBO_PRE_BLOOM_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBOPreBloomShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "FBO_BLOOM_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBOBloomShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "FBO_DOF_SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					cVideoDriver::GetInstance()->m_pFBODOFShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
			}
		}

		if (_strcmpi(scan_buffer, "#Objects") == 0)
		{
			hasReadData = true;
			int id;
			while (true)
			{
				ReadLine(pFile, buffer);
				iStart = ScanString(buffer, scan_buffer);

				if (scan_buffer[0] == '#' || feof(pFile))
				{
					break;
				}
				else if (_strcmpi(scan_buffer, "ID") == 0)
				{
					pObject = new cObject();
					m_vObjects.push_back(pObject);

					ScanNumberInt32(buffer, &id, iStart);
					pObject->m_ID = id;
				}
				else if (_strcmpi(scan_buffer, "SHADER") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					pObject->m_pShader = (cShader*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_SHADER, id));
				}
				else if (_strcmpi(scan_buffer, "MODEL") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					pObject->m_pModel = (cModel*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_MODEL, id));
				}
				else if (_strcmpi(scan_buffer, "TEXTURE") == 0)
				{
					ScanNumberInt32(buffer, &id, iStart);
					pObject->m_vTextures.push_back((cTexture*)(cResourceManager::GetInstance()->GetResourceByID(cResourceManager::RM_TEXTURE, id)));
				}
				else if (_strcmpi(scan_buffer, "POSITION") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &pObject->m_position.x, iStart);
					iStart = ScanNumberFloat32(buffer, &pObject->m_position.y, iStart);
					ScanNumberFloat32(buffer, &pObject->m_position.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "ROTATE") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &pObject->m_rotate.x, iStart);
					iStart = ScanNumberFloat32(buffer, &pObject->m_rotate.y, iStart);
					ScanNumberFloat32(buffer, &pObject->m_rotate.z, iStart);
				}
				else if (_strcmpi(scan_buffer, "SCALE") == 0)
				{
					iStart = ScanNumberFloat32(buffer, &pObject->m_scale.x, iStart);
					iStart = ScanNumberFloat32(buffer, &pObject->m_scale.y, iStart);
					ScanNumberFloat32(buffer, &pObject->m_scale.z, iStart);
				}
			}
		}
	}

	fclose(pFile);
}

void cSceneManager::Init()
{
	for (unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		m_vObjects[i]->Init();
	}
}

void cSceneManager::Update(float deltaTime)
{
	for (unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		m_vObjects[i]->Update(deltaTime);
	}
}

void cSceneManager::Render()
{
	for (unsigned int i = 0; i < m_vObjects.size(); i++)
	{
		m_vObjects[i]->Render();
	}
}
